"use strict";
var Uploader = (function ($) {

    // *********************************************************
    // ************************ 上传插件 ************************
    // *********************************************************
    var UPLOADER = function (option) {
        this.option = $.extend({}, this.dOption, option || {});
        this.info = {};
        this.widget = undefined;
        this.handler = undefined;
        this.init();
    };

    var UPLOADER_PROTOTYPE = {
        'dOption': {
            'type': 'image', // 上传插件类型 : image / file  / callback
            'max': 1, // 最大文件数量 
            'size': '2m', // 文件大小限制
            'ext': 'jpg,jpeg,png,gif,ico,doc,docx,xls,xlsx,pdf,zip', // 允许上传的类型
            'width': '200px', // 文件图标宽度
            'height': '100px', // 文件图标高度

            'url': 'upload.php', // 文件上传接口地址
            'swf': 'pluploader/Moxie.swf', // flash 插件路径

            // 'resize': { 'width': 1080, 'height': 1920, 'quality': 100, 'crop': false }, // 图片压缩

            'el': '', // input element
            'format': 'string', // 数据格式 : string / json
            'hideDel': true, // 自动隐藏删除按钮
            'click': true, // 点击文件新窗口打开

            'error': alert, // 错误回调
        },

        'init': function () {
            this.id = Math.floor('UPLOADER-' + (Math.random() * 1000000));
            this.option.readonly = this.option.el.attr('readonly') == 'readonly';
            this.widget = new WIDGET(this);

            var files = this.getValue();
            for (var i = 0; i < files.length; i++) {
                i < this.option.max && this.widget.insert(files[i]);
            }
            this.widget.initStatus = true;
            this.widget.showButton(files.length < this.option.max);
            this.option.button = this.widget.button;

            // 微信环境上传图片时使用微信上传
            if (window.wx && window.wx.config && this.option.type == 'image') {
                this.option.handler = 'wechat';
            } else {
                this.option.handler = 'pluploader';
            }
            this.handler = new HANDLER(this);
        },

        // 读取文件列表
        'getValue': function () {
            var val = $.trim(this.option.el.val());
            var files = [];

            if (val !== '') {
                // 使用 [,] 分隔的字符串
                if (this.option.format == 'string') {
                    val = val.split(',');
                    for (var i = 0; i < val.length; i++) {
                        files.push({ 'url': val[i] });
                    }
                }
                // 使用 json 格式
                else if (this.option.format == 'json') {
                    try {
                        eval("files=" + val);
                    } catch (e) { }
                }
                // 无效的配置
                else {
                    window.console && window.console.log("Invalid option.format : ".this.option.format);
                }
            }
            window.console && window.console.log("GET VALUE", files);
            return files;
        },

        // 更新文件列表
        'setValue': function (files) {
            var val = [];
            // 使用 [,] 分隔的字符串
            if (this.option.format == 'string') {
                for (var i = 0; i < files.length; i++) {
                    val.push(files[i].url);
                }
                val = val.join(',');
            }
            // 使用 json 格式
            else if (this.option.format == 'json') {
                try {
                    val = JSON.stringify(files);
                } catch (e) { val = ''; }
            }

            this.option.el.val(val);
            window.console && window.console.log("SET VALUE", val);
            this.widget.showButton(files.length < this.option.max);
        }
    };

    $.extend(UPLOADER.prototype, UPLOADER_PROTOTYPE);

    // *********************************************************
    // ************************ UI *****************************
    // *********************************************************
    var WIDGET = function (o) {
        this.o = o;
        this.option = o.option;
        this.container = undefined;
        this.instance = undefined;
        this.button = undefined;
        this.initStatus = false;
        this.init();
    };

    var WIDGET_PROTOTYPE = {

        'init': function () {
            var instanceMap = {
                'image': WIDGET_IMAGE,
                'file': WIDGET_FILE
            };
            this.instance = typeof this.option.type == 'function' ? this.option.type : new instanceMap[this.option.type]();
            this.container = $('<div></div>').addClass("uploader-container uploader-container-" + this.instance.skin);
            this.button = this.newButton();
            this.container.append(this.button);
            this.option.el.hide().after(this.container);
        },

        'insert': function (file) {
            var box = this.newBox(file);
            this.draw(box, file);
        },

        'showButton': function (show) {
            show && !this.option.readonly ? this.button.show() : this.button.hide();
        },

        'newButton': function () {
            var style = {
                'width': this.option.width,
                'height': this.option.height,
                'line-height': this.option.height,
                'font-size': parseInt(this.option.height) / 1.2
            };
            var button = $('<div>+</div>').addClass("uploader-box uploader-add uploader-add-" + this.instance.skin).css(style).hide();
            return button;
        },

        'newBox': function () {
            var context = this;
            var box = $('<div></div>').addClass("uploader-box uploader-box-" + this.instance.skin).css({
                'width': this.option.width,
                'height': this.option.height
            });
            var progress = $('<div></div>').addClass("uploader-progress uploader-progress-" + this.instance.skin).text('0%').css({
                'line-height': this.option.height
            });
            var del = $('<div></div>').addClass("uploader-del").click(function () {
                box.remove();
                context.change();
                return false;
            });
            this.option.hideDel ? del.hide() : del.show();

            // 只读模式
            this.option.readonly ? box.addClass("uploader-box-readonly") : box.append(del);

            box.append(progress);
            this.button.before(box);
            this.change(true);
            return box;
        },

        'draw': function (box, file) {
            var context = this;
            if (this.option.click) {
                box.click(function () {
                    window.open(file.url);
                    return false;
                });
            }
            box.data('file', file);
            box.find('.uploader-progress').hide();
            this.change();
            this.instance.draw(box, file);
        },

        'change': function (emptyBox) {
            if (!emptyBox && this.initStatus) {
                var files = [];
                this.container.find('.uploader-box').not('.uploader-add').each(function () {
                    $(this).data('file') && files.push($(this).data('file'));
                });
                this.o.setValue(files);
            }
            this.o.handler && this.o.handler.change();
        },

        // files = {"id":"o_1bqf0fc83k1jcv617fg1jg0sa48","name":"The-Hobbit-1_1440x900.jpg","percent":0}
        'add': function (file) {
            if (this.container.find('.uploader-box').not('.uploader-add').length + 1 > this.option.max) {
                return false;
            }
            var box = this.newBox().attr('data-file-id', file.id);
            return true;
        },

        // file = {"id":"o_1bqf0fc83k1jcv617fg1jg0sa48","name":"The-Hobbit-1_1440x900.jpg","percent":20};
        'progress': function (file) {
            var box = this.container.find('.uploader-box[data-file-id="' + file.id + '"]');
            box.find('.uploader-progress').text(file.percent + '%');
        },

        // file = {"id":"o_1bqf0fc83k1jcv617fg1jg0sa48","name":"The-Hobbit-1_1440x900.jpg","percent":100,"url":"fc83k1jcv617fg1jg0sa4.jpg"};
        'done': function (file) {
            var box = this.container.find('.uploader-box[data-file-id="' + file.id + '"]');
            this.draw(box, file.result);
        },

        'error': function (file, error) {
            var callback = this.option.error;
            if (file && file.id) {
                this.container.find('.uploader-box[data-file-id="' + file.id + '"]').remove();
            }
            callback(error);
            return false;
        }
    };

    $.extend(WIDGET.prototype, WIDGET_PROTOTYPE);


    // *********************************************************
    // ************************ 图片UI *************************
    // *********************************************************
    var WIDGET_IMAGE = function () { };

    var WIDGET_IMAGE_PROTOTYPE = {
        'skin': 'image',
        'draw': function (box, file) {
            var image = $('<img />').addClass('uploader-content uploader-content-image').attr('src', file.url);
            box.append(image);
        }
    };

    $.extend(WIDGET_IMAGE.prototype, WIDGET_IMAGE_PROTOTYPE);

    // *********************************************************
    // ************************ 文件UI *************************
    // *********************************************************
    var WIDGET_FILE = function () { };

    var WIDGET_FILE_PROTOTYPE = {
        'skin': 'file',
        'draw': function (box, file) {
            var name = file.name || file.url.split('/').pop();
            var ext = name.split('.').pop();
            var icon = $("<div></div>").addClass('uploader-content uploader-content-icon uploader-content-icon-' + ext).css({
                'width': box.height(),
                'height': box.height()
            });
            var title = $("<div></div>").addClass('uploader-content uploader-content-title').text(name).css({
                'width': box.width() - box.height() - 20
            });
            box.append(icon, title);
        }
    };

    $.extend(WIDGET_FILE.prototype, WIDGET_FILE_PROTOTYPE);

    // *********************************************************
    // ************************ 上传组件 ************************
    // *********************************************************
    var HANDLER = function (o) {
        this.o = o;
        this.option = o.option;
        this.instance = undefined;
        this.init();
    }

    var HANDLER_PROTOTYPE = {
        'init': function () {
            var instanceMap = {
                'pluploader': HANDLER_PLUPLOADER,
                'wechat': HANDLER_WECHAT
            };
            this.instance = new instanceMap[this.option.handler](this.option, this.callback());
        },

        'callback': function () {
            var context = this;
            return {
                'add': function (file) {
                    window.console && window.console.log('ADD', file);
                    return context.o.widget.add(file);
                },
                'progress': function (file) {
                    window.console && window.console.log('PROGRESS', file);
                    return context.o.widget.progress(file);
                },
                'error': function (file, error) {
                    window.console && window.console.log('ERROR', error);
                    return context.o.widget.error(file, error);
                },
                'done': function (file) {
                    window.console && window.console.log('DONE', file);
                    return context.o.widget.done(file);
                }
            };
        },

        'change': function () {
            this.instance.change();
        }
    };

    $.extend(HANDLER.prototype, HANDLER_PROTOTYPE);

    // *********************************************************
    // ************************ pluploader 上传 ****************
    // *********************************************************
    var HANDLER_PLUPLOADER = function (option, callback) {
        this.option = option;
        this.callback = callback;
        this.up = undefined;
        this.init();
    };

    var HANDLER_PLUPLOADER_PROTOTYPE = {

        'init': function () {
            var url = (this.option.url.indexOf('?') === -1 ? '?' : '&') + '_UPLOADER_ID_' + (Math.random());
            var pluploaderOption = {
                // 上传地址
                url: this.option.url,
                // 运行方式
                runtimes: 'html5,flash,silverlight,html4',
                // 选择文件按钮
                browse_button: this.option.button[0],
                // 容器元素
                container: this.option.button.parent()[0],
                // 分段尺寸(动态设置)
                // chunk_size: '10kb',
                // 重命名文件
                unique_names: false,
                // 文件选择器过滤
                filters: {
                    'max_file_size': this.option.size,
                    'mime_types': [{
                        'title': "请选择图片",
                        'extensions': "*"
                    }]
                },
                // 图片压缩
                resize: this.option.resize,
                // flash 插件路径
                flash_swf_url: this.option.swf,
                // silverlight 插件路径
                silverlight_xap_url: this.option.xap,
                multiple_queues: true,
                // multipart: false,
                max_file_count: this.option.max,
                // 多文件选择
                multi_selection: true,
                // 文件上传域名称
                file_data_name: 'kcs_uploader_file',
                // 附加参数
                multipart_params: {}
            };

            this.up = new plupload.Uploader(pluploaderOption);
            this.up.init();

            // 使用 html5 上传的时候使用分段上传
            if (this.up.runtime == 'html5') {
                this.up.setOption('chunk_size', '100kb');
            } else {
                this.up.setOption('chunk_size', '0');
            }

            this.bind();
        },

        'bind': function () {
            var context = this;

            // 选择文件后回调
            this.up.bind('FilesAdded', function (uploader, files) {
                for (var i = 0; i < files.length; i++) {
                    var names = files[i].name.split('.');
                    if (names.length < 2 || context.option.ext.split(',').indexOf(names.pop()) == -1) {
                        context.option.error("请选择后缀为:" + context.option.ext + "的文件!");
                        status = false;
                        for (var j = 0; j < files.length; j++) {
                            uploader.removeFile(files[j]);
                        }
                        return false;
                    }
                    if (!context.callback.add(files[i])) {
                        uploader.removeFile(files[i]);
                    }
                }
                files.length && uploader.start();
            });

            // 上传进度更新回调
            this.up.bind('UploadProgress', function (uploader, file) {
                context.callback.progress(file);
            });

            // 文件上传完成回调
            this.up.bind('FileUploaded', function (uploader, file, response) {
                try {
                    var responseJson = JSON.parse(response.response);
                } catch (e) {
                    responseJson = { 'error': { 'code': -1, 'message': '系统繁忙' } };
                }

                if (responseJson.error) {
                    return context.callback.error(file, responseJson.error.message);
                }

                file.result = responseJson.result;
                context.callback.done(file);
            });

            // 错误回调
            this.up.bind('Error', function (uploader, error) {
                window.console && window.console.log(error);
                var i18n = {
                    "Upload URL might be wrong or doesn't exist.": "上传的URL可能是错误的或不存在。",
                    "You must specify either browse_button or drop_element.": "您必须指定 browse_button 或者 drop_element。",
                    "Init error.": "初始化错误。",
                    "%s specified, but cannot be found.": "%s 已指定，但是没有找到。",
                    "Image format either wrong or not supported.": "图片格式错误或者不支持。",
                    "HTTP Error.": "HTTP 错误。",
                    "Error: File too large:": "错误: 文件太大:",
                    "Duplicate file error.": "重复文件错误。",
                    "File size error.": "文件大小错误。",
                    "Error: Invalid file extension:": "错误：无效的文件扩展名:",
                    "%s already present in the queue.": "%s 已经在当前队列里。",
                    "Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.": "超限。<b>%s</b> 支持最大 %wx%hpx 的图片。",
                    "Upload element accepts only %d file(s) at a time. Extra files were stripped.": "每次只接受同时上传 %d 个文件，多余的文件将会被删除。",
                    "Runtime ran out of available memory.": "运行时已消耗所有可用内存。",
                    "File count error.": "文件数量错误。",
                    "File extension error.": "文件扩展名错误。",
                }
                context.callback.error(uploader, i18n[error.message] || error.message);
            });
        },

        'change': function () {
            this.up.refresh();
        }
    };

    $.extend(HANDLER_PLUPLOADER.prototype, HANDLER_PLUPLOADER_PROTOTYPE);

    // *********************************************************
    // ************************ 微信上传 ************************
    // *********************************************************
    var HANDLER_WECHAT = function () { };

    // *********************************************************
    // ************************ 导出插件 ************************
    // *********************************************************
    var pluglin = function (option) {
        return new UPLOADER(option);
    }

    // 注册 jQuery 插件
    $.fn.uploader = function (option) {
        option = option || {};
        return this.each(function () {
            option.el = $(this);
            pluglin(option);
        });
    }

    return pluglin;
})(jQuery);
